package test;

import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.List;

import javax.smartcardio.Card;
import javax.smartcardio.CardChannel;
import javax.smartcardio.CardException;
import javax.smartcardio.CardTerminal;
import javax.smartcardio.TerminalFactory;

public class SmartCardReader {
	private static Object syncObj = new Object();
	private static CardChannel cardChannel = null;
	private static Card card = null;

	/**
	 * 执行apdu指令
	 * 
	 * @param command
	 * @return
	 */
	public static String transmit(String command) {
		return byteToHex(transmit(hexTobyte(command)));
	}

	/**
	 * 执行apdu指令
	 * 
	 * @param command
	 * @return
	 */
	public static byte[] transmit(byte[] command) {

		byte[] response = null;
		synchronized (syncObj) {
			try {
				response = new byte[1024];
				int len = cardChannel.transmit(ByteBuffer.wrap(command),
						ByteBuffer.wrap(response));
				if (len <= 0)
					return null;
				response = Arrays.copyOf(response, len);
			} catch (Exception e) {
				return null;
			}
		}
		return response;
	}

	public static byte[] getATR() {
		if (beginCard())
			return card.getATR().getBytes();
		else
			return null;
	}

	public static boolean beginCard() {
		try {
			if (card != null)
				return true;
			else {
				synchronized (syncObj) {
					TerminalFactory factory;
					List<CardTerminal> terminals;
					CardTerminal cardTerminal;
					factory = TerminalFactory.getDefault();
					try {
						terminals = factory.terminals().list();
						if (terminals == null || terminals.size() == 0) {
							throw new Exception("读卡器未连接");
						}
						for (CardTerminal t : terminals) {
							if (!t.isCardPresent())
								continue;
							cardTerminal = t;
							for (String s : new String[] { "T=0", "T=1" }) {
								card = cardTerminal.connect(s);
								cardChannel = card.getBasicChannel();
								if (cardChannel != null)
									break;
							}
						}
					} catch (Exception e) {
						throw e;
					}
				}

			}
			return true;
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		}
	}

	public static boolean closeCard() {
		synchronized (syncObj) {
			try {
				if (cardChannel != null) {
					card.disconnect(false);
					// cardChannel.close();
				}
				return true;
			} catch (CardException e) {
				e.printStackTrace();
				return false;
			} finally {
				card = null;
				cardChannel = null;
			}
		}
	}

	public static byte[] hexTobyte(String str) {
		int len = str.length();
		byte[] b = new byte[len / 2];
		String stmp = null;
		for (int i = 0; i < len / 2; i++) {
			stmp = str.substring(i * 2, i * 2 + 2);
			b[i] = (byte) Integer.parseInt(stmp, 16);
		}
		return b;
	}

	public static String byteToHex(byte[] b) {
		if (b == null)
			return null;
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < b.length; i++) {
			if (((int) b[i] & 0xff) < 0x10) {
				sb.append("0");
			}
			sb.append(Long.toString((int) b[i] & 0xff, 16));
		}
		return sb.toString();
	}
}
